package net.liteheaven.dtimer.timer

import android.annotation.SuppressLint
import android.app.PendingIntent
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.os.Build
import android.os.PersistableBundle
import net.liteheaven.dtimer.XLog
import net.liteheaven.dtimer.timer.DTimerConst.Companion.EXTRA_TIMER_ID


@SuppressLint("StaticFieldLeak")
/**
 * Created by LiangYu on 2018/7/30.
 */
object DTimerManager{

    private val tokenMap : HashMap<Int, DToken> = HashMap()
    private val pendingIntentMap : HashMap<Int, PendingIntent> = HashMap()
    private val receiver: DTimerReceiver = DTimerReceiver()
    private lateinit var context: Context
    private var globalCallbacks: HashSet<DTimerCallback> = HashSet()

    fun attach(context: Context){
        DTimerManager.context = context.applicationContext
        val intentFilter = IntentFilter()
        intentFilter.addAction(DTimerConst.ACTION_D_TIMER)
        DTimerManager.context.registerReceiver(receiver, intentFilter)
    }

    fun detach(context: Context){
        context.applicationContext.unregisterReceiver(receiver)
    }

    fun registerCallback(callback: DTimerCallback){
        globalCallbacks.add(callback)
    }

    fun unregisterCallback(callback: DTimerCallback){
        globalCallbacks.remove(callback)
    }

    fun addTimer(timerId: Int, delay: Long, once: Boolean): DToken {
        var token : DToken? = tokenMap[timerId]
        // ID已存在，释放原计时器
        if (token != null){
            token.cancel()
        }
        token = DToken(timerId, delay, once)

        tokenMap[timerId] = token
        startTimer(token)

        return token
    }

    @SuppressLint("NewApi")
    private fun startTimer(token: DToken){
        val once = token.once
        val delay = token.delay
        val id = token.id
        val context = context

        XLog.i("startTimer id = $id delay = $delay once = $once")
        if (greaterThanL()) {
            val bundle = PersistableBundle()
            bundle.putInt(EXTRA_TIMER_ID, id)
            JobUtil.scheduleJob(context, id, delay, bundle)
        } else {
            val intent = Intent(DTimerConst.ACTION_D_TIMER)
            intent.putExtra(EXTRA_TIMER_ID, id)
            val pendingIntent = AlarmManagerUtil.scheduleBroadcast(context, id, intent, delay)
            pendingIntentMap[id] = pendingIntent
        }
    }

    fun stopTimer(timerId: Int){
        if (greaterThanL()) {
            JobUtil.cancelJob(context, timerId)
        } else {
            val pi = pendingIntentMap[timerId]
            if (pi != null){
                AlarmManagerUtil.cancelPendingIntent(context, pi)
            }
        }
        releaseTimer(timerId)
    }

    private fun dispatchOnTimer(timerId: Int){
        XLog.i("dispatchOnTimer id = $timerId")
        // 遍历全局回调
        globalCallbacks.forEach {
            it.onTimer(timerId)
        }
    }

    internal fun dispatch(timerId: Int){
        var token = tokenMap[timerId]
        if (token != null){
            if (token.once){
                dispatchOnTimer(timerId)
                releaseTimer(timerId)
            }else{
                dispatchOnTimer(timerId)
                startTimer(token)
            }
        }
    }

    private fun releaseTimer(timerId: Int){
        XLog.i("releaseTimer id = $timerId")
        var token : DToken? = tokenMap[timerId]
        if (token != null){
            // 释放token对象
            tokenMap.remove(timerId)
        }

        if (!greaterThanL()) {
            // 如果是低版本，尝试释放pendingIntent
            val pi = pendingIntentMap[timerId]
            if (pi != null){
                pendingIntentMap.remove(timerId)
            }
        }
    }

    private fun greaterThanL(): Boolean {
        return Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP
        //return false
    }
}
